//package com.tianji.promotion.service.impl;
//
//import com.tianji.common.exceptions.BadRequestException;
//import com.tianji.common.exceptions.BizIllegalException;
//import com.tianji.common.utils.StringUtils;
//import com.tianji.common.utils.UserContext;
//import com.tianji.promotion.domain.po.Coupon;
//import com.tianji.promotion.domain.po.ExchangeCode;
//import com.tianji.promotion.domain.po.UserCoupon;
//import com.tianji.promotion.enums.CouponStatus;
//import com.tianji.promotion.enums.ExchangeCodeStatus;
//import com.tianji.promotion.mapper.CouponMapper;
//import com.tianji.promotion.mapper.UserCouponMapper;
//import com.tianji.promotion.service.IExchangeCodeService;
//import com.tianji.promotion.service.IUserCouponService;
//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
//import com.tianji.promotion.utils.CodeUtil;
//import lombok.RequiredArgsConstructor;
//import org.springframework.aop.framework.AopContext;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//
//import java.time.LocalDateTime;
//
///**
// * <p>
// * v1 用户领取优惠券的记录，是真正使用的优惠券信息 服务实现类
// * </p>
// *
// * @author friday
// * @since 2024-01-16
// */
//@Service
//@RequiredArgsConstructor
//public class UserCouponServiceImpl extends ServiceImpl<UserCouponMapper, UserCoupon> implements IUserCouponService {
//
//    private final CouponMapper couponMapper;
//    private final IExchangeCodeService exchangeCodeService;
//
//    //用户领取优惠券
//    @Override
//    //@Transactional
//    public void receiveCoupon(Long couponId) {
//        //1.根据id查询优惠券  做相关校验
//        if (couponId == null){
//            throw new BadRequestException("非法参数");
//        }
//        Coupon coupon = couponMapper.selectById(couponId);
//        if (coupon == null){
//            throw new BadRequestException("该优惠券不存在");
//        }
//        if (coupon.getStatus() != CouponStatus.ISSUING){
//            throw new BadRequestException("该优惠券未发放");
//        }
//        LocalDateTime now = LocalDateTime.now();
//        if (now.isBefore(coupon.getIssueBeginTime()) ||now.isAfter(coupon.getIssueEndTime())){
//            throw new BadRequestException("该优惠券已过期或未开始发放");
//        }
//        if (coupon.getTotalNum() <= 0 || coupon.getIssueNum() >= coupon.getTotalNum()){
//            throw new BadRequestException("该优惠券库存不足");
//        }
//        Long userId = UserContext.getUser();
//        /*//获取当前用户  对该优惠券 已领数量  user_coupon   条件user_id coupon_id  数量
//        Integer count = this.lambdaQuery()
//                .eq(UserCoupon::getUserId, userId)
//                .eq(UserCoupon::getCouponId, couponId)
//                .count();
//        if (count != null && count >= coupon.getUserLimit()){
//            throw new BadRequestException("该优惠券已达到领取上限");
//        }
//        //2.优惠券的已发放数量 +1
//        couponMapper.incrIssueNum(couponId); //采用这种方式，烤炉并发控制，后期仍需修改
//        //3.生成用户券
//        saveUserCoupon(userId,coupon);*/
////        //先加锁，然后再开启事务
////        synchronized (userId.toString().intern()) {
////            checkAndCreateUserCoupon(userId, coupon, null);
////        }
//        synchronized (userId.toString().intern()){
//            //从aop上下文中获取当前类的代理对象
//            IUserCouponService userCouponServiceProxy = (IUserCouponService) AopContext.currentProxy();
//            //checkAndCreateUserCoupon（userId，coupon，nuLL）;//这种写法是调用原对象的方法
//            userCouponServiceProxy.checkAndCreateUserCoupon(userId, coupon,null);//这种写法调用代理对象的方法，方法是有事务处理的
//        }
//    }
//    //兑换码兑换优惠券
//    @Override
//    @Transactional
//    public void exchangeCoupon(String code) {
//        //1.校验code是否为空
//        if (StringUtils.isBlank(code)){
//            throw new BadRequestException("非法参数");
//        }
//        //2.解析兑换码得到自增id
//        long serialNum = CodeUtil.parseCode(code); //解析兑换码得到自增id
//        //3.判断兑换码是否已兑换 采用redis的bitmap结构 setbit key offset 1 如果方法返回true代表兑换码已兑换
//        boolean result = exchangeCodeService.updateExchangeCodeMark(serialNum,true);
//        if (result){
//            throw new BizIllegalException("该兑换码已兑换");
//        }
//        try {
//            //4.判断兑换码是否存在 根据自增id查询 主键查询
//            ExchangeCode exchangeCode = exchangeCodeService.getById(serialNum);
//            if (exchangeCode == null){
//                throw new BizIllegalException("该兑换码不存在");
//            }
//            //5.判断是否过期
//            LocalDateTime now = LocalDateTime.now();
//            LocalDateTime expiredTime = exchangeCode.getExpiredTime();
//            if (now.isAfter(expiredTime)){
//                throw new BizIllegalException("该兑换码已过期");
//            }
//            //校验并生成用户券
//            Long userId = UserContext.getUser();
//            //查询优惠券信息
//            Coupon coupon = couponMapper.selectById(exchangeCode.getExchangeTargetId());
//            if (coupon == null){
//                throw new BizIllegalException("该优惠券不存在");
//            }
//            //6.判断是否超出限领数量  7.优惠券已发放数量 +1  8.生成用户券 9.更新兑换码状态
//            checkAndCreateUserCoupon(userId,coupon,serialNum);
//
//        }catch (Exception e){
//            //10.将兑换码的状态重置 （如果事务回滚，只是操作数db的事务回滚，操作redis需要手动回滚）
//            exchangeCodeService.updateExchangeCodeMark(serialNum,false);
//            throw e;
//        }
//
//
//    }
//    @Transactional
//    public void checkAndCreateUserCoupon(Long userId, Coupon coupon, Long serialNum) {
//        //Long类型-128~127之间是同一个对象    超过该区问则是不同的对象
//        //Long.toString方法底层是new String,所以还是不同的对象
//        //Long.toString.intern() intern方法是强制从常量池中取字符串
//        //1.获取当前用户  对该优惠券 已领数量  user_coupon   条件user_id coupon_id  数量
//        Integer count = this.lambdaQuery()
//                .eq(UserCoupon::getUserId, userId)
//                .eq(UserCoupon::getCouponId, coupon.getId())
//                .count();
//        if (count != null && count >= coupon.getUserLimit()){
//            throw new BadRequestException("该优惠券已达到领取上限");
//        }
//        //2.优惠券的已发放数量 +1
//        couponMapper.incrIssueNum(coupon.getId()); //采用这种方式，烤炉并发控制，后期仍需修改
//        //3.生成用户券
//        saveUserCoupon(userId,coupon);
//
//        if (serialNum != null){
//            //修改兑换码状态
//            exchangeCodeService.lambdaUpdate()
//                    .set(ExchangeCode::getStatus, ExchangeCodeStatus.USED)
//                    .set(ExchangeCode::getUserId, userId)
//                    .eq(ExchangeCode::getId, serialNum)
//                    .update();
//        }
//    }
//
//    //保存优惠券
//    private void saveUserCoupon(Long userId, Coupon coupon) {
//        // 1.基本信息
//        UserCoupon uc = new UserCoupon();
//        uc.setUserId(userId);
//        uc.setCouponId(coupon.getId());
//        // 2.有效期信息
//        LocalDateTime termBeginTime = coupon.getTermBeginTime(); //优惠券使用 开始时间
//        LocalDateTime termEndTime = coupon.getTermEndTime(); //优惠券使用 结束时间
//        if (termBeginTime == null) {
//            termBeginTime = LocalDateTime.now();
//            termEndTime = termBeginTime.plusDays(coupon.getTermDays());
//        }
//        uc.setTermBeginTime(termBeginTime);
//        uc.setTermEndTime(termEndTime);
//        // 3.保存
//        save(uc);
//    }
//}
